/*
 * Author: aple
 *
 * Created on 2015年10月9日, 上午10:07
 */

#ifndef file_afat_TAB_M_H
#define	file_afat_TAB_M_H

#include "stdint.h"
#include "rtctime.h"

#ifdef	__cplusplus
extern "C" {
#endif	

#define AFAT_NAME_SIZE        24

	typedef enum
	{
		FILE_AFAT_ERR_NONE = 0,
		FILE_AFAT_ERR_RENAME = 1,
		FILE_AFAT_ERR_PTAB = 2,
		FILE_AFAT_ERR_LEN = 3,
		FILE_AFAT_ERR_FULL = 4,
		FILE_AFAT_ERR_NO_FILE = 5,
		FILE_AFAT_ERR_NO_SITE = 6,
		FILE_AFAT_ERR_TAB_CRC = 7,
		FILE_AFAT_ERR_ADDR = 8,
		FILE_AFAT_ERR_OPT_MODE = 9,
		FILE_AFAT_ERR_HAL = 10,
	}file_afat_err_type;

	enum file_afat_mode_type
	{
		 FILE_AFAT_MODE_NONE    =   0,
		 FILE_AFAT_MODE_READ   =    1,
		 FILE_AFAT_MODE_WRITE   =   2,
		 FILE_AFAT_MODE_MODIFY  =   4,
	};
	
	#define FILE_AFAT_ATTR_EDIT       (1UL<<0)
	
	/*------------------------------------------------------------*
	*  文件按照文件名保存
	*  用于一次性存储文件系统，只有读写，无删除
	*-------------------------------------------------------------*/

	// 文件信息
	typedef struct
	{
		int32_t addr_base;
		int32_t  size;      //<0为无效文件
		int32_t  mem_alloc; 
		uint32_t attr;
		char name[AFAT_NAME_SIZE];
	} afat_tab_type;
	
	// 硬件描述
	typedef struct
	{
		afat_tab_type *tab;					//Y-文件信息表
		int16_t tab_len;					//Y-文件信息表长度 表格长度应为tab-len+1以上，索引tab_len用于存储校验信息	
		int32_t write_alain;				//Y-写入新文件边界对齐 , 2^n
		int32_t erase_alain;				//Y- 2^n
		int32_t mem_size;					//Y- 存储器尺寸
		
		// TAB
		void(*tab_save)(void);				//Y-分配表存储 //该接口内应读回校验 //存储长度 为 tab_len+1
		void(*tab_read)(void);				//Y-分配表读取 //读取长度 为 tab_len+1
		
		// IO
		uint8_t (*write)(uint32_t addr, int32_t len, void *pdat); //Y-文件存储区写
		uint8_t (*read)(uint32_t addr, int32_t len, void *pdat); //Y-文件存储区读	
		uint8_t (*erase)(uint32_t addr);
		uint8_t (*flush)(void);					//如果外部使用了写入页缓冲，此接口在写结束时刷缓冲,不需要时设为0即可
	} file_afat_cg_type;
	
	// 文件操作对象
	struct file_afat_obj_str
	{
		int16_t act_file_amount;    //X-有效文件数
		int32_t new_file_addr;		//X-打开写文件时以此作为文件内容起始地址，仅在关闭保存文件时更改
		int32_t erase_now_addr;		//X写入数据时检测更新
		
		const file_afat_cg_type *cfg;
	};
	
	typedef struct file_afat_obj_str file_afat_obj_type;

	// 文件操作状态信息
	struct file_afat_file_str
	{
		int32_t seelk;						// 指示当前正在操作文件的指针
		enum file_afat_mode_type opt_mode;	// 操作模式
		
		int16_t site_in_tab;				// 当前文件在分配表中的位置
		uint32_t wr_alain_real;				// 真实写对齐方式
		afat_tab_type info;					// 当前文件信息
		file_afat_obj_type *fat;
		
	};

	typedef struct file_afat_file_str file_afat_fil_type;
	
	//读取文件分配表，并初始化 act_file_amount
	file_afat_err_type afat_init(file_afat_obj_type *obj);

	//存储文件分配表
	file_afat_err_type afat_save(file_afat_obj_type *obj);

	//清除文件分配表
	file_afat_err_type afat_clr(file_afat_obj_type *obj);

	// file read opt
	file_afat_err_type afat_file_open_rd(file_afat_obj_type *obj, file_afat_fil_type *fil, char *name);
	file_afat_err_type afat_file_seek(file_afat_fil_type *fil, int32_t site);
	file_afat_err_type afat_file_read(file_afat_fil_type *fil, void *dat, int32_t Len, int32_t * LenBack);
	
	// file write opt。文件写入只允许再单任务中操作
	// 打开文件API,size 不为0会为文件分配指定大小的存储空间，该类文件内容后续可修改，size需对齐在擦除块边界
	// 如果是nand类flash，应保证除最后一页外，其余写入长度应为页尺寸整数倍。或者外部加数据页缓冲。
	file_afat_err_type afat_file_open_wr(file_afat_obj_type *obj, file_afat_fil_type *fil, char *name, uint32_t size); 
	file_afat_err_type afat_file_write(file_afat_fil_type *fil, void *dat, int32_t Len);
	file_afat_err_type afat_file_close(file_afat_fil_type *fil);
	
	// 文件需要后期修改内容时应使用指定尺寸打开写文件，否则文件根据写入自动生长。
	// 指定文件大小时，文件不在自动生长，并禁止写入超出尺寸。
	// 可修改文件修改时必须全文件写入，禁止通过seelk半截写入
	// 可修改文件内部对齐到块边界

#ifdef	__cplusplus
}
#endif

#endif	/* file_afat_TAB_M_H */
